package com.avit.tv.kui.dialog;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Build;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.WindowManager;
import androidx.annotation.ColorInt;
import com.avit.tv.kui.AvitDialog;
import com.avit.tv.kui.R;
import com.avit.tv.kui.utils.Log;

import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


/**
 * dialog 主控制器
 *
 * @author like
 * @date 2020/6/23
 */
public class DialogController implements DialogClickListener {

    private Context context;
    private AvitDialog root;

    private static DialogController dialogController;

    private Method okMethod;

    private Method cancelMethod;

    private WeakReference<Object> weakReferenceClazz;

    private String dialogTagString;

    private int NO_DIALOG_TAG = -0x00010000;
    private int dialogTagInt = NO_DIALOG_TAG;

    private  WindowManager windowManager;
    private  WindowManager.LayoutParams layoutParams;
    private DialogConfigValue dialogConfigValue;

    private boolean isGlobal;
    /**
     * 描述dialog的事件
     */
    public enum ClickEvent {
        OK_CONFIRM,
        CANCEL
    }

    public DialogController init(Context context) {
        this.context = context;
        windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        root = new AvitDialog(context.getApplicationContext());
        layoutParams = new WindowManager.LayoutParams();
        dialogConfigValue = new DialogConfigValue();
        setContentView();
        return this;
    }

    public static DialogController getInstance() {
        if (dialogController == null) {
            synchronized (DialogController.class) {
                if (dialogController == null) {
                    dialogController = new DialogController();
                }
            }
        }
        return dialogController;
    }

    private DialogController(){}

    /**
     * 注册方法把持类的对象
     *
     * @param o
     */
    public DialogController registerDialogEvent(Object o) {
        if (weakReferenceClazz != null) {
            weakReferenceClazz.clear();
            weakReferenceClazz = null;
        }
        weakReferenceClazz = new WeakReference<Object>(o);
        Method[] declaredMethods = getDeclaredMethods(o.getClass());
        for (Method method : declaredMethods) {
            OnDialogListener annotation = method.getAnnotation(OnDialogListener.class);
            if (annotation != null) {
                method.setAccessible(true);
                initMethods(annotation, method);
            }
        }
        return this;
    }

    private void initMethods(OnDialogListener annotation, Method method) {
        if (annotation.event().equals(ClickEvent.OK_CONFIRM)) {
            okMethod = method;
        } else if (annotation.event().equals(ClickEvent.CANCEL)) {
            cancelMethod = method;
        }
    }

    private Method[] getDeclaredMethods(Class<?> klass) {
        try {
            return klass.getDeclaredMethods();
        } catch (NoClassDefFoundError e) {
            throw new IllegalArgumentException("on live class has not be inited");
        }
    }

    private void useMethod(Method method) {
        try {
            Object o = weakReferenceClazz.get();
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 0) {
                method.invoke(o);
            } else if (parameterTypes.length == 1) {
                if (parameterTypes[0].toString().equals(String.class.toString()) && !TextUtils.isEmpty(dialogTagString)) {
                    method.invoke(o, dialogTagString);
                } else if (parameterTypes[0].toString().equals(int.class.toString())) {
                    method.invoke(o, dialogTagInt);
                } else {
                    throw new ExceptionInInitializerError("first params only support String type even type was initialized");
                }
            } else {
                throw new ExceptionInInitializerError("only support one or no parameter method");
            }
        } catch (IllegalAccessException e) {
            Log.e(this, "IllegalAccessException : " + e.getMessage());
        } catch (InvocationTargetException e) {
            Log.e(this, "InvocationTargetException : " + e.getMessage());
        } catch (ExceptionInInitializerError e) {
            Log.e(this, "ExceptionInInitializerError : " + e.getMessage());
        }

    }

    private void setContentView() {
        layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
        layoutParams.format = PixelFormat.TRANSPARENT;
        root.setDialogClickListener(this);
        root.initFocus(true);
        initGlobal();
    }

    private void initGlobal(){
        if (isGlobal){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
            } else {
                layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
            }
        }else
            layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
    }

    /**
     * 设置 dialog 坐标
     *
     * @param x
     * @param y
     * @return
     */
    public DialogController setXy(int x, int y) {
        layoutParams.gravity = Gravity.TOP | Gravity.START;
        layoutParams.x = x;
        layoutParams.y = y;
        return this;
    }

    /**
     * 重置dialog坐标，并为屏幕中间
     */
    public void resetXy() {
        layoutParams.gravity = Gravity.CENTER;
        layoutParams.x = 0;
        layoutParams.y = 0;
    }

    /**
     * 监听ok键的回调
     * {@hide}
     */
    @Override
    public void onConfirm() {
        dismiss();
        toUseMethod(okMethod);
    }

    /**
     * 监听cancel键的回调
     * {@hide}
     */
    @Override
    public void onCancel() {
        dismiss();
        toUseMethod(cancelMethod);
    }

    private void toUseMethod(Method method) {
        if (weakReferenceClazz == null || weakReferenceClazz.get() == null) return;
        if (method != null) {
            useMethod(method);
        }
    }

    /**
     * 设置 String 类型的标记，用来标记dialog，从而辨析其类别
     *
     * @param dialogTagString
     * @return
     */
    public DialogController setDialogTagString(String dialogTagString) {
        this.dialogTagString = dialogTagString;
        return this;
    }

    /**
     * 设置 int 类型的标记，用来标记dialog从而辨析其类别
     *
     * @param dialogType
     * @return
     */
    public DialogController setDialogTagInt(int dialogType) {
        this.dialogTagInt = dialogType;
        return this;
    }

    public void show() {
        try {
            if (root.getParent() == null)
                windowManager.addView(root, layoutParams);
            else
                windowManager.updateViewLayout(root, layoutParams);
        } catch (Exception e) {
            Log.e(this, "error:" + e.getMessage());
        }
    }

    public void dismiss() {
        try {
            if (root.getParent() != null)
                windowManager.removeViewImmediate(root);

        } catch (Exception e) {
            Log.e(this, "remove error:" + e.getMessage());
        } finally { // dialog 归位
            resetDialogStatus();
        }
    }

    /**
     * 重置dialog显示
     */
    private void resetDialogStatus() {
        resetXy();
        root.initFocus(true);
        root.setOnlyOneButton(false);
    }


    /**
     * 设置dialog 内部的size
     * 设置 1个参数 为只设置 dialog 的 title 尺寸
     * 设置 2个参数 为只设置 dialog 的 title 和 content 尺寸
     * 设置 3个参数 为设置 dialog 的 title、content、button 的尺寸
     *
     * @param sizes
     * @return
     */
    public DialogController setSize(int... sizes) {
        if (sizes.length > 0)
            root.setTitleSize(sizes[0]);
        if (sizes.length > 1)
            root.setContentSize(sizes[1]);
        if (sizes.length > 2)
            root.setButtonSize(sizes[2]);
        return this;
    }

    /**
     * dialog 全局初始化
     *
     * @param dialogConfigValue
     * @return
     */
    public DialogController initConfig(DialogConfigValue dialogConfigValue) {
        this.dialogConfigValue = dialogConfigValue;
        initContents();
        initColor();
        initDrawable();
        return this;
    }


    /**
     * 精简 dialog 处理方法 ， 仅仅只需要修改content 内容
     *
     * @param content
     * @return
     */
    public DialogController setDefaultDialogContent(String content) {
        setDefaultDialogContent("", content);
        return this;
    }

    /**
     * 精简 dialog 处理方法,仅仅只需要修改title和content
     *
     * @param title
     * @param content
     * @return
     */
    public DialogController setDefaultDialogContent(String title, String content) {
        setDefaultDialogContent(title, content, true);
        return this;
    }

    /**
     * 默认设置dialog方法，当dialog config过后，锁定了某一主题，可以在代码中简单的使用此方法来控制dialog显示内容
     *
     * @param title
     * @param content
     * @param isOkFocus
     * @return
     */
    public DialogController setDefaultDialogContent(String title, String content, boolean isOkFocus) {
        dialogConfigValue.setTitle(title);
        dialogConfigValue.setContent(content);
        root.initFocus(isOkFocus);
        initContents();
        return this;
    }

    private void initContents() {
        root.setTitle(checkDefault(dialogConfigValue.getTitle(), ""));
        root.setContent(checkDefault(dialogConfigValue.getContent(), ""));
        root.setOkText(checkDefault(dialogConfigValue.getOkValue(), context.getResources().getString(R.string.ok_value)));
        root.setCancelText(checkDefault(dialogConfigValue.getCancelValue(), context.getResources().getString(R.string.cancel_value)));
    }

    private void initColor() {
        root.setTitleColor(checkDefaultColor(dialogConfigValue.getTitleColor(), Color.WHITE));
        root.setContentColor(checkDefaultColor(dialogConfigValue.getContentColor(), Color.WHITE));
        root.setOkTextColor(checkDefaultColor(dialogConfigValue.getOkTextColor(), Color.WHITE));
        root.setCancelTextColor(checkDefaultColor(dialogConfigValue.getCancelTextColor(), Color.WHITE));
        root.setOkButtonColor(checkDefaultColor(dialogConfigValue.getOkButtonColor(), Color.TRANSPARENT));
        root.setCancelButtonColor(checkDefaultColor(dialogConfigValue.getCancelButtonColor(), Color.TRANSPARENT));
        root.setButtonFocusColor(checkDefaultColor(dialogConfigValue.getButtonFocusColor(), Color.TRANSPARENT));
        root.setButtonFocusColor(checkDefaultColor(dialogConfigValue.getButtonFocusTextColor(), Color.WHITE));
    }

    private void initDrawable() {
        root.setOkButtonDrawable(dialogConfigValue.getOkDialogDrawable());
        root.setCancelButtonDrawable(dialogConfigValue.getCancelDialogDrawable());
        root.setButtonFocusDrawable(dialogConfigValue.getDialogButtonFocusBackground());
        root.setBackground(dialogConfigValue.getDialogBackground());
    }


    private String checkDefault(String value, String defaultValue) {
        if (TextUtils.isEmpty(value)) return defaultValue;
        else return value;
    }

    private int checkDefaultColor(@ColorInt int value, @ColorInt int defaultValue) {
        if (value == 0) return defaultValue;
        else return value;
    }


    /**
     * 设置是否只显示一个button
     *
     * @param isShow
     * @return
     */
    public DialogController setOnlyButtonShow(boolean isShow) {
        root.setOnlyOneButton(isShow);
        return this;
    }

    /**
     * 设置自动消失
     *
     * @return
     */
    public DialogController setAutoDismiss() {
        root.postDelayed(new Runnable() {
            @Override
            public void run() {
                dismiss();
            }
        }, 3500);
        return this;
    }

    public void unRegisterDialogEvent() {
        Log.d(this, "dialog controller unregister");
        if (weakReferenceClazz != null)
            weakReferenceClazz.clear();
        weakReferenceClazz = null;
        okMethod = null;
        cancelMethod = null;
        dialogTagString = null;
        dialogTagInt = NO_DIALOG_TAG;
        resetDialogStatus();
    }

    /**
     * 设置是否全局
     * @param global
     */
    public DialogController setGlobal(boolean global) {
        isGlobal = global;
        initGlobal();
        return this;
    }
}
